package com.gitee.wsl.compose.ui.richtext

import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Modifier
import com.gitee.wsl.compose.ui.richtext.handler.LinkClickHandler
import com.gitee.wsl.compose.ui.richtext.theme.RichTextStyle
import com.gitee.wsl.compose.ui.richtext.theme.RichTextThemeProvider

object RichText

/**
 * RichText implementation that integrates with Material 3 design.
 *
 * If the consumer app has small composition trees or only uses RichText in
 * a single place, it would be ideal to call this function instead of wrapping
 * everything under [RichTextMaterialTheme].
 */
@Composable
fun RichText(
    modifier: Modifier = Modifier,
    style: RichTextStyle? = null,
    linkClickHandler: LinkClickHandler? = null,
    children: @Composable RichTextScope.() -> Unit
) {
    RichTextMaterialTheme {
        BasicRichText(
            modifier = modifier,
            style = style,
            linkClickHandler = linkClickHandler,
            children = children
        )
    }
}

/**
 * Wraps the given [child] with Material Theme integration for [BasicRichText].
 *
 * This function also keeps track of the parent context by using CompositionLocals
 * to not apply Material Theming if it already exists in the current composition.
 */
@Composable
internal fun RichTextMaterialTheme(
    child: @Composable () -> Unit
) {
    val isApplied = LocalMaterialThemingApplied.current

    if (!isApplied) {
        RichTextThemeProvider(
            textStyleProvider = { LocalTextStyle.current },
            contentColorProvider = { LocalContentColor.current },
            textStyleBackProvider = { textStyle, content ->
                ProvideTextStyle(textStyle, content)
            },
            contentColorBackProvider = { color, content ->
                CompositionLocalProvider(LocalContentColor provides color) {
                    content()
                }
            }
        ) {
            CompositionLocalProvider(LocalMaterialThemingApplied provides true) {
                child()
            }
        }
    } else {
        child()
    }
}

private val LocalMaterialThemingApplied = compositionLocalOf { false }